#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/select.h>

#define PORT 8888
#define MAX_CLIENTS 100  // 最大客户端数（受限于FD_SETSIZE，默认1024）

int main() {
    // 1. 创建监听套接字
    int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_fd < 0) {
        perror("socket error");
        exit(EXIT_FAILURE);
    }

    // 2. 绑定端口
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);

    if (bind(listen_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("bind error");
        exit(EXIT_FAILURE);
    }

    // 3. 开始监听
    if (listen(listen_fd, 10) < 0) {
        perror("listen error");
        exit(EXIT_FAILURE);
    }

    fd_set read_fds, temp_fds;
    FD_ZERO(&read_fds);
    FD_ZERO(&temp_fds);
    FD_SET(listen_fd, &read_fds);  // 初始时监听套接字加入读集合

    int max_fd = listen_fd;  // 初始最大文件描述符

    printf("Server started, waiting for connections...\n");

    while (1) {
        temp_fds = read_fds;  // 每次select前复制集合（select会修改原集合）

        // 4. 调用select监控读事件
        int ready_fds = select(max_fd + 1, &temp_fds, NULL, NULL, NULL);
        if (ready_fds < 0) {
            perror("select error");
            continue;
        }

        // 5. 处理就绪的描述符
        for (int fd = 0; fd <= max_fd; fd++) {
            if (FD_ISSET(fd, &temp_fds)) {
                // 5.1 处理新连接（监听套接字就绪）
                if (fd == listen_fd) {
                    struct sockaddr_in client_addr;
                    socklen_t client_len = sizeof(client_addr);
                    int client_fd = accept(listen_fd, (struct sockaddr*)&client_addr, &client_len);
                    if (client_fd < 0) {
                        perror("accept error");
                        continue;
                    }
                    printf("New client connected: fd=%d\n", client_fd);
                    FD_SET(client_fd, &read_fds);  // 将新客户端加入读集合
                    if (client_fd > max_fd) {
                        max_fd = client_fd;  // 更新最大FD
                    }
                }
                // 5.2 处理已连接客户端的数据接收
                else {
                    char buf[1024] = {0};
                    int recv_len = recv(fd, buf, sizeof(buf), 0);
                    if (recv_len <= 0) {  // 客户端关闭连接或出错
                        printf("Client fd=%d disconnected\n", fd);
                        close(fd);
                        FD_CLR(fd, &read_fds);  // 从集合中移除
                    } else {  // 接收数据并回发
                        printf("Received from fd=%d: %s\n", fd, buf);
                        send(fd, buf, recv_len, 0);
                    }
                }
            }
        }
    }

    close(listen_fd);
    return 0;
}